﻿/********************************************************************************
** 作者： samfeng
** 创始时间：2012-7-15
** 描述：
** 功能：XML类
*********************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Xml;
using System.Xml.Serialization;


namespace DBA.Common
{
    public class Xml
    {
        private XmlDocument doc;
        private ObjectAttrbuteSaveType saveType;

        public Xml(string filePath)
        {
            try
            {
                this.SaveType = this.saveType;
                this.XmlFilePath = filePath;
                this.doc = new XmlDocument();
                this.doc.Load(this.XmlFilePath);
            }
            catch
            {
                throw new Exception("指定路径:" + filePath + "的Xml文件加载错误!");
            }
        }

        public Xml(string filePath, ObjectAttrbuteSaveType saveType)
            : this(filePath)
        {
            this.SaveType = saveType;
        }

        public static T GetObject<T>(string fileName)
        {
            Type type = typeof(T);
            XmlSerializer serializer = new XmlSerializer(type);
            using (XmlReader reader = XmlReader.Create(fileName))
            {
                return (T)serializer.Deserialize(reader);
            }
        }

        public XmlNode GetXmlNode(string path)
        {
            return this.doc.SelectSingleNode(path);
        }

        public XmlNodeList GetXmlNodeList(string path)
        {
            return this.doc.SelectNodes(path);
        }

        public XmlElement ListToXml<T>(List<T> list, string parentName, string childName)
        {
            string name = VerificationHelper.IsNullOrEmpty(parentName) ? (typeof(T).Name + "List") : parentName;
            string nodeName = VerificationHelper.IsNullOrEmpty(childName) ? typeof(T).Name : childName;
            XmlElement element = this.doc.CreateElement(name);
            foreach (T local in list)
            {
                element.AppendChild(this.ObjectToXml<T>(local, nodeName));
            }
            return element;
        }

        public XmlElement ObjectToXml<T>(T obj, string nodeName)
        {
            string name = VerificationHelper.IsNullOrEmpty(nodeName) ? obj.GetType().Name : nodeName;
            XmlElement element = this.doc.CreateElement(name);
            if (obj != null)
            {
                foreach (PropertyInfo info in obj.GetType().GetProperties())
                {
                    object obj2 = info.GetValue(obj, null);
                    string data = (obj2 == null) ? string.Empty : obj2.ToString();
                    XmlCDataSection newChild = this.doc.CreateCDataSection(data);
                    switch (this.SaveType)
                    {
                        case ObjectAttrbuteSaveType.Attribute:
                            {
                                XmlAttribute node = this.doc.CreateAttribute(info.Name);
                                node.Value = data;
                                element.Attributes.Append(node);
                                break;
                            }
                        case ObjectAttrbuteSaveType.ChildNode:
                            {
                                XmlElement element2 = this.doc.CreateElement(info.Name);
                                element2.AppendChild(newChild);
                                element.AppendChild(element2);
                                break;
                            }
                    }
                }
            }
            return element;
        }

        public void SaveListToXml<T>(List<T> list)
        {
            this.doc.RemoveAll();
            this.doc.AppendChild(this.doc.CreateXmlDeclaration("1.0", "utf-8", string.Empty));
            this.doc.AppendChild(this.ListToXml<T>(list, null, null));
            this.doc.Save(this.XmlFilePath);
        }

        public static void SaveObject(object input, string fileName)
        {
            XmlSerializer serializer = new XmlSerializer(input.GetType());
            using (new MemoryStream())
            {
                using (XmlWriter writer = XmlWriter.Create(fileName))
                {
                    serializer.Serialize(writer, input);
                }
            }
        }

        public void SaveObjectToXml(object obj)
        {
            this.doc.RemoveAll();
            this.doc.AppendChild(this.doc.CreateXmlDeclaration("1.0", "utf-8", string.Empty));
            this.doc.AppendChild(this.ObjectToXml<object>(obj, null));
            this.doc.Save(this.XmlFilePath);
        }

        public List<T> XmlToList<T>() where T : new()
        {
            string name = typeof(T).Name;
            string path = "/" + name + "List/" + name;
            return this.XmlToList<T>(path);
        }

        public List<T> XmlToList<T>(string path) where T : new()
        {
            return ConvertHelper.XmlToList<T>(this.XmlFilePath, path, this.SaveType);
        }

        public List<T> XmlToList<T>(XmlNodeList noList) where T : new()
        {
            return ConvertHelper.XmlToList<T>(noList, this.SaveType);
        }

        public T XmlToObject<T>() where T : new()
        {
            string path = "/" + typeof(T).Name;
            return this.XmlToObject<T>(path);
        }

        public T XmlToObject<T>(string path) where T : new()
        {
            XmlNode xmlNode = this.GetXmlNode(path);
            if (xmlNode == null)
            {
                throw new Exception("未能加载对应的节点!");
            }
            return this.XmlToObject<T>(xmlNode);
        }

        public T XmlToObject<T>(XmlNode no) where T : new()
        {
            return ConvertHelper.XmlToObject<T>(no, this.SaveType);
        }

        public ObjectAttrbuteSaveType SaveType
        {
            get
            {
                return this.saveType;
            }
            set
            {
                this.saveType = value;
            }
        }

        public string XmlFilePath { get; set; }

        public enum ObjectAttrbuteSaveType
        {
            Attribute,
            ChildNode
        }
    }
}

